/*
    This file is part of Raptor.

    Raptor is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    Raptor is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with Raptor.  If not, see <http://www.gnu.org/licenses/>.

 */

#ifndef __XMLFILELOADER_H__
#define __XMLFILELOADER_H__

#include <QObject>
#include <QHttp>
#include <QNetworkProxy>
#include <QFile>
#include <QDir>
#include <QUrl>
#include <QTimer>
#include <QDateTime>
#include <QDomDocument>
#include <QPointer>

/*! \class xmlFileLoader

    \brief Downloads files.

    QObject that parses an xml file for loading files from the hoster specified in the xml file.
 */

class xmlFileLoader : public QObject
{
    Q_OBJECT

    public:

            enum E_MODE
        {
            MODE_FREE,
            MODE_PREMIUM,
            MODE_LOGIN,
            MODE_GET_SIZE,
        };

        enum E_ERROR
        {
            ERROR_NO_ERROR,
            ERROR_XML,
            ERROR_HTTP,
            ERROR_FILE,
            ERROR_ATTR,
            ERROR_GET_VAR,
            ERROR_LOGIN,
            ERROR_GET_SIZE,
        };

        enum E_STATE
        {
            STATE_LOAD_XML,
            STATE_ERROR,
            STATE_RUNNING,
            STATE_FINISHED,
            STATE_WAITING,
            STATE_DOWNLOADING,
            STATE_STOPPED,
            STATE_STALLED,
            STATE_HISTORY,
            STATE_DELETE,
        };

        enum E_ACTION_TYPE
        {
            TYPE_NO_FOUND,
            TYPE_OPEN_URL,
            TYPE_METHOD_GET,
            TYPE_METHOD_GET_DOWNLOAD,
            TYPE_METHOD_POST,
            TYPE_METHOD_POST_DOWNLOAD,
            TYPE_REGEXP,
            TYPE_MULTI_REGEXP,
            TYPE_GET_SIZE,
            TYPE_STEP,
            TYPE_DO_STEP,
            TYPE_HALT,
            TYPE_HALT_LOGIN,
            TYPE_HALT_GET_SIZE,
            TYPE_WAIT,
            TYPE_PREPARE_DOWNLOAD,
            TYPE_FINISH_DOWNLOAD,
            TYPE_SELECT_MIRROR,
            TYPE_CHECK_FILE,
            TYPE_CHECK_SIZE,
            TYPE_CHECK_CONTENT,
            TYPE_DUMMY,
            TYPE_DELETE_FILE,
            TYPE_SET_STATE,
            TYPE_BREAK_CHECK,
            TYPE_SET_COOKIE,
            TYPE_SAVE_COOKIE,
            TYPE_LOAD_SETTINGS,
            TYPE_HEADER,
            TYPE_WAIT_HTTP,
            TYPE_MODE,
            TYPE_BOOL_FCT,
            TYPE_SET_ERROR,
            TYPE_EMIT_STATE,
        };

        struct S_WAITFOR
        {
            QDomNode node;
            int it;

            S_WAITFOR(QDomNode const& n, int const& i) : node(n), it(i) {}
        };

        xmlFileLoader();
        ~xmlFileLoader();

        bool isValidHoster(const QString &host);
        void loadXml(const QString &xmlFile);

        bool setLink(const QUrl &newUrl);
        void setFile(const QString &newFile);
        void setFolder(const QString &newFolder);
        void setDownloadDir(const QString &newFolder);
        void setId(const int &newId);
        void setMode(const E_MODE &newMode);
        void setLogId(const int &newId);

        int setProxy(QNetworkProxy const &proxy);

        void start();
        void stop();
        void login(const QString &user, const QString &pass);
        void getSize();

        int state();
        int error();
        int progress();
        int mode();
        double speed();
        int timeLeft();
        QString link();
        QString errorStr();
        int logId();

        QDateTime downloadStart();
        uint fileSize();
        uint downloaded();

        QPointer<QFile> downloadFile();

    public slots:

    signals:

        void loginFinished(const int id, const bool error);
        void getSizeFinished(const int id, const bool error);
        void downloadFinished(const int &id, const bool &error);
	void deleteMe(int const& id, bool const& error);
        void statusMsg(const int &id, const QString &msg);
        void changeMode(const int &id, const xmlFileLoader::E_MODE mode);

    private:

        bool verbose;

        QHttp http;
        QByteArray response;
        QString cookie;
        QString page;

        bool reinitLoop;
        bool waitForHttp;
        int waitInsertAt;
        QList<S_WAITFOR> waitHttp;

        int waitingId;

        uint m_fileSize;
        uint m_downloaded;
        int m_progress;

        E_STATE m_state;
        E_ERROR m_error;
        E_MODE m_mode;

        int step;

        //timer
        QTimer waitTimer;
        int m_timeLeft;
        int wait;
        int timerStep;
        ///timer

        bool continueCheck;

        QMap<QString, QString> regExpResults;
        QMap<QString, QStringList> regExpListResults;

        QDomDocument domHoster;

        int id;
        int m_logId;
        int maxConnectionsPerDownloads;

        QString m_errorStr;

        QUrl url;
        QString host;

        QPointer<QFile> m_downloadFile;

        QString file;
        QString folder;
        QDir downloadDir;

        QDateTime m_downloadStart;
        QDateTime downloadEnd;
        uint lastSize;

        double m_speed;
        QList<double> speedList;
        QTimer speedTimer;
        int smooth;
        int speedIntervall;

        bool loadXmlFile(const QString &xmlFile);
        void loadVar();

        void doStep();
        void doAction(const QDomNode &parent, const int startI=0);

        int parseType(const QString &type);
        int parseState(const QString &state);

        void switchAction(const QDomNode &action);
        bool switchResult(const QDomNode &result);

        void setSpeed(const double &newSpeed);

        QString getVar(const QString &var);
        QStringList getListVar(const QString &var);

        void addVar(const QString &key, const QString &value);
        void checkAttributes(const QDomNode &node, const QStringList &attributes);
        void handleError(int const& e);
        QDomNodeList getDomNodeListByMode(xmlFileLoader::E_MODE const& _mode);

    protected:


    private slots:

        //void slot_http_done(bool httpError);
        void slot_http_requestFinished(int requestId, bool httpError);
        void slot_http_readyRead(const QHttpResponseHeader & resp);
        void slot_http_dataReadProgress(int done, int total);
        void slot_http_sslErrors(const QList<QSslError> & errors);

        void slot_waitTimer_timeout();
        void slot_speedTimer_timeout();
};
#endif
